iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
1

本文同步分享於個人blog

  • 定義


依賴反轉原則(DIP)的定義有兩點:

1. High-level modules should not depend on low-level modules. Both should depend on abstractions.

翻譯年糕:高層模組不應該依賴低層模組,兩者皆應依賴於抽象。

2. Abstractions should not depend on details. Details should depend on abstractions.

翻譯年糕:抽象不應該依賴細節,細節應該依賴於抽象。

高層低層是相對關係,其實也就是呼叫者與被呼叫者。而細節指的是具體的實作,相較於抽象的穩定,細節的變化較多。

比如說,到賣場消費要付款時,我使用信用卡付款:

class Payment{
    public void pay(CreditCard creditCard){
        creditCard.pay();
    }
}

class CreditCard{
    public void pay(){
        System.out.println("信用卡付款");
    }
}

public class Bank {
    public static void main(String args[]) {
      Payment p = new Payment();
      p.pay(new CreditCard());
    }
}

output

信用卡付款

DIP1

依照上面的程式碼,就順利的使用信用卡完成了付款了!信用卡即是低層次模組,而付款這個行為就是高層次模組。可以發現付款這個行為跟信用卡有直接的關係。想想我們從以前用現金、金融卡、信用卡到現在電子支付甚至虛擬貨幣...等等。隨著時代的進步,會有更多的付款方式出現,但如果照著上面的方式去撰寫系統的話,每當出現一個新的付款方式,就要去更動一次程式,這不是個理想的狀態。

  • Dependency Inversion Principle


上述提到,付款依附著信用卡,並不是我們想看到的。於是我們可以將付款行為抽出:

interface IPayment{
    public void pay();
}


class CreditCard implements IPayment{
    public void pay(){
        System.out.println("信用卡付款");
    }
}

class QRCode implements IPayment{
    public void pay(){
        System.out.println("QRCode付款");
    }
}

class Payment{
    public void pay(IPayment iPayment){
        iPayment.pay();
    }
}

public class Bank {
    public static void main(String args[]) {
      Payment p = new Payment();
      p.pay(new CreditCard());
      p.pay(new QRCode());
    }
}

output

信用卡付款
QRCode付款

DIP2

經過以上的修改,抽出了一個IPaymeny作為interface,付款方式CreditCard和QRCode去實作IPayment,而Payment只要將只要將IPayment引入即可。在實作前他不需要知道付款方式是什麼,在實作時把對應的方式放入即可。如此一來,假設未來要增加虛擬貨幣的付款,只需要新增一個blockchain的class即可,不需要再動到Payment。

剛剛我們一直在解釋定義的第一點,而第二點抽象不應該依賴細節,細節應該依賴於抽象又是什麼意思呢?我們可以把信用卡以及QRCode看成付款的細節(變化度高),而這兩個付款方式應該依照著抽象類別(穩定度高)IPayment去實作,而不是IPayment去照著信用卡或是QRCode的方向走。

  • 小結


DIP的優點
1. 减少class間的耦合性,提高系统的穩定性
2. 降低開發時的風險
3. 提高系統可讀及維護性
DIP的目標

高層模組(Payment)不應該依賴低層模組(CreditCard),兩者皆應依賴於抽象(IPayment)

抽象(IPayment)不應該依賴細節(CreditCard),細節(CreditCard)應該依賴於抽象(IPayment)

  • 範例程式碼


範例1:未使用DIP
範例2:使用DIP

  • References


依賴倒置原則 (Dependency-Inversion Principle, DIP)
依賴反轉原則
依賴反轉原則 Dependency Inversion Principle (DIP)
SOLID 原則 - Dependency Inversion Principle(依賴反轉原則)
依赖倒置原则DIP


上一篇
[Day06] 介面隔離原則 | Interface Segregation Principle
下一篇
[Day08] 合成/聚合複用原則 | Composite/Aggregate Reuse Principle
系列文
從生活中認識Design Pattern30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言